package com.cauli.gateway.config;

import cn.dev33.satoken.context.SaHolder;
import cn.dev33.satoken.jwt.StpLogicJwtForSimple;
import cn.dev33.satoken.reactor.filter.SaReactorFilter;
import cn.dev33.satoken.router.SaHttpMethod;
import cn.dev33.satoken.router.SaRouter;
import cn.dev33.satoken.stp.StpLogic;
import cn.dev33.satoken.stp.StpUtil;
import com.cauli.utils.util.ResultResponse;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/**
 * @author Cauli
 * @date 2022/12/13 11:27
 * @description 注册拦截器 配置类
 */
@Configuration
public class SaTokenConfigure{
    /**
     * Sa-Token 整合 jwt (Simple 简单模式)
     *
     * @return
     */
    @Bean
    public StpLogic getStpLogicJwt() {
        return new StpLogicJwtForSimple();
    }

    /**
     * 注册 [Sa-Token全局过滤器]
     *
     * @return
     */
    @Bean
    public SaReactorFilter getSaReactorFilter() {
        return new SaReactorFilter()
                // 拦截地址 - 拦截全部path
                .addInclude("/**")
                // 开放地址
                .addExclude("/favicon.png")
                // 鉴权方法：每次访问进入
                // 全局认证函数
                .setAuth(obj -> {
                    SaRouter
                            // 拦截的所有接口
                            .match("/**")
                            // 忽略所有登陆相关接口
                            .notMatch("/account/**")
                            // 忽略所有个人信息相关接口
                            .notMatch("/manage/profile/**")
                            // 忽略获得文件下载链接相关接口
                            .notMatch("/file/fileTransfer/getFileUrl/**")
                            // 忽略获取站点信息列表相关接口
                            .notMatch("/manage/config/get")
                            // 忽略获取所有的公告相关接口
                            .notMatch("/manage/notice/list")
                            // 忽略所有接口文档相关接口
                            .notMatch("/doc.html",
                                    "/doc.html*",
                                    "/doc.html/*",
                                    "/webjars/**",
                                    "/img.icons/**",
                                    "/swagger-resources/**",
                                    "/**/v2/api-docs")
                            // 要执行的校验动作，可以写完整的 lambda 表达式
                            .check(r -> StpUtil.checkLogin());
                })
                // 异常处理函数
                .setError(e -> {
                    return ResultResponse.fail().message(e.getMessage());
                })
                // 前置函数：在每次认证函数之前执行
                .setBeforeAuth(obj -> {
                    // ---------- 设置跨域响应头 ----------
                    SaHolder.getResponse()
                            // 允许指定域访问跨域资源
                            .setHeader("Access-Control-Allow-Origin", "*")
                            // 允许所有请求方式
                            .setHeader("Access-Control-Allow-Methods", "POST, GET, PUT, DELETE, OPTIONS")
                            // 有效时间
                            .setHeader("Access-Control-Max-Age", "3600")
                            // 允许的header参数
                            .setHeader("Access-Control-Allow-Headers", "*");
                    // 如果是预检请求，则立即返回到前端
                    SaRouter.match(SaHttpMethod.OPTIONS)
                            .free(r -> System.out.println("--------OPTIONS预检请求，不做处理--------"))
                            .back();
                });
    }
}

